package ChannelTutorial.Demo04;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;

/**
 * Demo04 - Channel 生命周期详解 - 客户端
 * 
 * 学习目标：
 * 1. 理解 Channel 的完整生命周期
 * 2. 掌握各个生命周期回调方法的触发时机
 * 3. 学习如何优雅关闭连接
 */
@Slf4j
public class Client {

    public static void main(String[] args) throws Exception {
        log.info("=== Channel 生命周期演示 - 客户端 ===\n");
        
        // 演示 1：正常的连接生命周期
        log.info("\n========================================");
        log.info("演示 1: 正常的连接生命周期");
        log.info("========================================\n");
        demo1_NormalLifecycle();
        
        Thread.sleep(2000);
        
        // 演示 2：异常断开的生命周期
        log.info("\n========================================");
        log.info("演示 2: 异常断开的生命周期");
        log.info("========================================\n");
        demo2_AbnormalClose();
        
        Thread.sleep(2000);
        
        // 演示 3：优雅关闭
        log.info("\n========================================");
        log.info("演示 3: 优雅关闭连接");
        log.info("========================================\n");
        demo3_GracefulClose();
        
        Thread.sleep(2000);
        System.exit(0);
    }

    /**
     * 演示 1：正常的连接生命周期
     * 
     * 完整的生命周期：
     * channelRegistered → channelActive → channelRead → channelReadComplete 
     * → channelInactive → channelUnregistered
     */
    private static void demo1_NormalLifecycle() throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) {
                        ch.pipeline().addLast(new ClientLifecycleHandler("Normal"));
                    }
                });
            
            // 1. 连接服务端
            ChannelFuture connectFuture = bootstrap.connect("localhost", 8080).sync();
            Channel channel = connectFuture.channel();
            
            // 2. 发送数据
            Thread.sleep(500);
            channel.writeAndFlush(
                Unpooled.copiedBuffer("Hello from normal client", StandardCharsets.UTF_8)
            );
            
            // 3. 等待一段时间
            Thread.sleep(1000);
            
            // 4. 正常关闭
            channel.close().sync();
            
        } finally {
            group.shutdownGracefully();
        }
    }

    /**
     * 演示 2：异常断开的生命周期
     * 
     * 当连接异常断开时，也会触发完整的生命周期回调
     */
    private static void demo2_AbnormalClose() throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) {
                        ch.pipeline().addLast(new ClientLifecycleHandler("Abnormal"));
                        ch.pipeline().addLast(new ExceptionHandler());
                    }
                });
            
            ChannelFuture connectFuture = bootstrap.connect("localhost", 8080).sync();
            Channel channel = connectFuture.channel();
            
            // 模拟异常：发送大量数据后立即关闭
            for (int i = 0; i < 10; i++) {
                channel.write(
                    Unpooled.copiedBuffer("Data " + i, StandardCharsets.UTF_8)
                );
            }
            channel.flush();
            
            // 立即关闭（可能有数据还未发送完成）
            Thread.sleep(100);
            channel.close().sync();
            
        } finally {
            group.shutdownGracefully();
        }
    }

    /**
     * 演示 3：优雅关闭连接
     * 
     * 优雅关闭的步骤：
     * 1. 停止接收新数据
     * 2. 发送完所有待发送的数据
     * 3. 释放资源
     * 4. 关闭连接
     */
    private static void demo3_GracefulClose() throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) {
                        ch.pipeline().addLast(new ClientLifecycleHandler("Graceful"));
                        ch.pipeline().addLast(new GracefulCloseHandler());
                    }
                });
            
            ChannelFuture connectFuture = bootstrap.connect("localhost", 8080).sync();
            Channel channel = connectFuture.channel();
            
            // 发送数据
            channel.writeAndFlush(
                Unpooled.copiedBuffer("Request graceful close", StandardCharsets.UTF_8)
            );
            
            Thread.sleep(500);
            
            // 优雅关闭
            log.info("[客户端-Graceful] 开始优雅关闭...");
            
            // 方式 1: 等待所有数据发送完成再关闭
            ChannelFuture lastWriteFuture = channel.writeAndFlush(
                Unpooled.copiedBuffer("Final message", StandardCharsets.UTF_8)
            );
            
            lastWriteFuture.addListener((ChannelFutureListener) future -> {
                if (future.isSuccess()) {
                    log.info("[客户端-Graceful] 最后的消息已发送，关闭连接");
                    future.channel().close();
                }
            });
            
            Thread.sleep(1000);
            
        } finally {
            group.shutdownGracefully();
        }
    }

    /**
     * 客户端生命周期处理器
     */
    @Slf4j
    static class ClientLifecycleHandler extends ChannelInboundHandlerAdapter {
        
        private final String name;
        
        public ClientLifecycleHandler(String name) {
            this.name = name;
        }

        @Override
        public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
            log.info("🟢 [客户端-{}] 1. handlerAdded - Handler 被添加到 Pipeline", name);
        }

        @Override
        public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
            log.info("🟢 [客户端-{}] 2. channelRegistered - Channel 注册到 EventLoop", name);
            ctx.fireChannelRegistered();
        }

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            log.info("🟢 [客户端-{}] 3. channelActive - Channel 激活（连接建立）", name);
            log.info("   [客户端-{}] 本地地址: {}", name, ctx.channel().localAddress());
            log.info("   [客户端-{}] 远程地址: {}", name, ctx.channel().remoteAddress());
            ctx.fireChannelActive();
        }

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            log.info("🟢 [客户端-{}] 4. channelRead - 读取数据", name);
            
            ByteBuf buf = (ByteBuf) msg;
            String data = buf.toString(StandardCharsets.UTF_8);
            log.info("   [客户端-{}] 收到: {}", name, data);
            
            buf.release();
            ctx.fireChannelRead(msg);
        }

        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
            log.info("🟢 [客户端-{}] 5. channelReadComplete - 本次读取完成", name);
            ctx.fireChannelReadComplete();
        }

        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            log.info("🔴 [客户端-{}] 6. channelInactive - Channel 失活（连接断开）", name);
            ctx.fireChannelInactive();
        }

        @Override
        public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
            log.info("🔴 [客户端-{}] 7. channelUnregistered - Channel 从 EventLoop 注销", name);
            ctx.fireChannelUnregistered();
        }

        @Override
        public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
            log.info("🔴 [客户端-{}] 8. handlerRemoved - Handler 从 Pipeline 移除", name);
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            log.error("❌ [客户端-{}] exceptionCaught - 发生异常: {}", name, cause.getMessage());
            ctx.close();
        }
    }

    /**
     * 异常处理器
     */
    @Slf4j
    static class ExceptionHandler extends ChannelInboundHandlerAdapter {
        
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            log.error("❌ [ExceptionHandler] 捕获异常", cause);
            
            // 发送错误信息给对端（如果连接还在）
            if (ctx.channel().isActive()) {
                ctx.writeAndFlush(
                    Unpooled.copiedBuffer("Error: " + cause.getMessage(), StandardCharsets.UTF_8)
                ).addListener(ChannelFutureListener.CLOSE);
            } else {
                ctx.close();
            }
        }
    }

    /**
     * 优雅关闭处理器
     */
    @Slf4j
    static class GracefulCloseHandler extends ChannelInboundHandlerAdapter {
        
        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            log.info("🔧 [GracefulClose] 执行清理工作...");
            
            // 在这里执行资源清理
            // 例如：关闭数据库连接、释放文件句柄等
            
            log.info("🔧 [GracefulClose] 清理完成");
            ctx.fireChannelInactive();
        }
    }
}

/*
=== 运行结果分析 ===

1. 完整的生命周期顺序：

   创建阶段：
   1. handlerAdded      - Handler 添加到 Pipeline
   2. channelRegistered - Channel 注册到 EventLoop
   3. channelActive     - Channel 激活（连接建立）

   工作阶段：
   4. channelRead          - 读取数据（可能多次）
   5. channelReadComplete  - 本次读取完成（可能多次）

   销毁阶段：
   6. channelInactive      - Channel 失活（连接断开）
   7. channelUnregistered  - Channel 从 EventLoop 注销
   8. handlerRemoved       - Handler 从 Pipeline 移除

=== 资源管理建议 ===

1. 连接建立时（channelActive）：
   - 初始化连接相关的资源
   - 发送认证信息
   - 记录连接日志

2. 数据读取时（channelRead）：
   - 处理业务逻辑
   - 及时释放 ByteBuf
   - 避免阻塞操作

3. 连接断开时（channelInactive）：
   - 关闭文件、数据库连接
   - 释放内存资源
   - 记录断开日志
   - 清理会话信息

4. 优雅关闭：
   - 等待所有数据发送完成
   - 清理所有资源
   - 记录关闭原因
*/

